home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Gold Collection / Software Vault - The Gold Collection (American Databankers) (1993).ISO / cdr49 / 105_01.zip / LIB.C < prev    next >
Text File  |  1993-06-09  |  17KB  |  660 lines

  1. /*addmoney will add dollars and cents which are presented in an array
  2. which is 6 unsigned integers. The first integer is the dollars of the 
  3. first number, the second integer the cents of the first number, the 
  4. third integer the dollars of the second number, and the fourth integer 
  5. the cents of the second number. The answer, which properly checks for
  6. overflow of the cents, has the dollars in the fifth integer and cents in 
  7. the sixth integer. This routine will only add money, it will not subtract!
  8. The maximum value permitted in the answer (and obviously in either of the
  9. values is $65535.99. There are no error checks. */
  10.  
  11. addmoney(money)
  12. unsigned money[];
  13. {
  14.     money[4] = money[0] + money[2];
  15.     money[5] = money[1] + money[3];
  16.     if (money[5] > 99)
  17.     {
  18.         money[5] -= 100;
  19.         money[4]++;
  20.     }
  21.     return;    
  22. }
  23.  
  24. /* chkdate will check an ASCII string to see if it is a proper date. A 
  25. ptoper date is one which has a number of 1 to 31 followed by a correct 
  26. 3-letter code. If an improper date is found, chkdate returns -1; else
  27. it returns the day of year where JAN 1 is a 1 and every month has 31
  28. days. */
  29.  
  30. chkdate(dd)
  31. char dd[];
  32. {
  33.     int i,j,k;
  34.     char dt[36];
  35.  
  36.     k = atoi(dd);
  37.     if (k < 1 || k > 31)
  38.         return(-1);
  39.     i = 0;
  40.     while(isdigit(dd[i++]));
  41.     for (j=0,i--;j<3;j++,i++)
  42.         dd[i] = toupper(dd[i]);
  43.     i -=3;
  44.     movmem("JANFEBMARAPRMAYJUNJULAUGSEPOCTNOVDEC",dt,36);
  45.     for(j = 0; j < 36; j+=3)
  46.         if(dt[j]==dd[i]&&dt[j+1]==dd[i+1]&&dt[j+2]==dd[i+2])
  47.             return(((j/3)*31) + k);
  48.     return(-1);
  49. }
  50.  
  51. /*comma checks a buffer (resbuf) at an index (j) for the nth comma (nbr).
  52. If it encounters an end-of-line(CR) or slash it returns a -1. Else it
  53. returns the index to the first character after the comma.*/
  54.  
  55. comma(resbuf,j,nbr)
  56. char resbuf[];
  57. int j;
  58. int nbr;
  59. {
  60.     int i;
  61.     for (i = 0; i < nbr; i++)
  62.     {
  63.         while (resbuf[j] != ',')
  64.         {
  65.             if (resbuf[j] == 13 || resbuf[j] == 92)
  66.                 return(-1);
  67.             j++;
  68.         }
  69.         j++;
  70.     }
  71.     return(j);
  72. }
  73. /*count counts the number of characters in the buffer (resbuf) from the 
  74. index (j) up to either the first comma,first slash, first end-of-line (CR),
  75. or end of buffer (control Z). It does not count blanks in the total. The 
  76. total number of characters is returned as an integer.*/
  77.  
  78. count(resbuf,j)
  79. char resbuf[];
  80. int j;
  81. {
  82.     int i;
  83.     for(i=0;resbuf[j]!=','&&resbuf[j]>26&&resbuf[j]!=92;j++) 
  84.     if(resbuf[j] != ' ')
  85.         i++;
  86.     return(i);
  87. }
  88.  
  89. /*count1 counts the number of characters in the buffer (resbuf) from the
  90. index (j) up to either the first comma,first slash, first end-of-line (CR),
  91. or end of buffer (control Z). It counts blanks in the total. The total number 
  92. of characters is returned as an integer. */
  93.  
  94. count1(resbuf,j)
  95. char resbuf[];
  96. int j;
  97. {
  98.     int i;
  99.     for (i=0;resbuf[j]!=','&&resbuf[j]>26&&resbuf[j]!=92;i++,j++);
  100.     return(i);
  101. }
  102.  
  103. /*error will print the alarm in the array (ss) and then hang until any 
  104. character is typed on the console. there are no error conditions or exit
  105. parameters*/
  106.  
  107. error(ss)
  108. char ss[];
  109. {
  110.  
  111.     printf("%s",ss);
  112.     bdos(1);
  113. }
  114.  
  115. /*findline will look for the first line of the buffer (resbuf) starting at the 
  116. index (j) which has a first character match with the character in flag. Since 
  117. findline first looks for the beginning of the nextline it is necessary to have
  118. a special case for j in order to get the very first line. Therefore if j is
  119. negative then the first character of the first line is also checked. If a match
  120. is found then the index to the character which matches is returned, else a -1
  121. is returned indicating no match found.*/
  122.  
  123. findline(resbuf,j,flag)
  124. char resbuf[];
  125. int j;
  126. char flag;
  127. {
  128.     if(j < 0)
  129.         if(resbuf[0] == flag)
  130.             return(0);
  131.     while((j = nextline(resbuf,j)) != -1)
  132.         if (toupper(resbuf[j]) == flag)
  133.             return(j);
  134.     return(j);
  135. }
  136.  
  137. /*getal is a special function used to retrieve airline information from
  138. the airline file. It matches the two characters in al against the first 2 
  139. characters of 32 byte groupings in the airline file. If it finds a match
  140. it returns the 32 byte array in buf1 and a exit parameter of zero. If it
  141. cannot find a match it returns -1.*/
  142.  
  143. getal(al,buf1,fd)
  144. char al[];
  145. char buf1[];
  146. int fd;
  147. {
  148.     int i,j;
  149.     for (i=0;;i++)
  150.     {
  151.         rwblk(fd,buf1,0,1,i);
  152.         for(j=0;j<128;j+=32)
  153.         {
  154.             if((buf1[j] =='Z')&&(buf1[j+1]=='Z'))
  155.                 return(-1);
  156.             if((buf1[j]==al[0])&&(buf1[j+1]==al[1]))
  157.             {
  158.                 for (i=0;i<32;i++,j++)
  159.                     buf1[i] = buf1[j];
  160.                 return(0);
  161.             }
  162.         }
  163.     }
  164. }
  165.  
  166. /*getcit is a special routine which matches a set of 3-byte city codes (plus
  167. a string-ending zero) against a file on disk. The city codes are in the 
  168. array city, and the number of entries is in count. The disk file has a 
  169. 16-byte array for each city which is moved into buf2. If all the cities 
  170. are found then a zero is returned, else a -1 is returned*/
  171.  
  172. getcit(city,buf1,buf2,count,fd)
  173. char city[];
  174. char buf1[];
  175. char buf2[];
  176. int count;
  177. int fd;
  178. {
  179.     int i,j,k,m,n;
  180.     n = 0;
  181.     for (i=0;;i++)
  182.     {    
  183.         rwblk(fd,buf1,0,1,i);
  184.         for(j=0;j<128;j+=16)
  185.         {
  186.             for (k=0;city[k] != 26;k+=4)
  187.             {
  188.                 if(stgcmp("ZZZ",&buf1[j],3))
  189.                     return(-1);
  190.                 if(stgcmp(&city[k],&buf1[j],3))
  191.                 {    
  192.                          movmem(&buf1[j],&buf2[k * 4],16);
  193.                     n++;   
  194.                     if(n==count)       
  195.                         return(0);
  196.                 }
  197.             }
  198.         }
  199.     }
  200. }
  201.  
  202. /*getdate will retrieve the date from the MPM function TOD and tranlate it 
  203. into a set of ASCII characters in the array date. It checks to see if the 
  204. TOD function has ever been run and if not prints an alarm to the operator
  205. and exits back to MPM. Else it returns the month as 2 digits followed by
  206. the day as 2 digits, followed by the last 2 digits of year. getdate does
  207. proper checks for leap year and different size months.*/
  208.  
  209. getdate(date)
  210. char date[];
  211. {
  212. int temp[3];
  213. int day_tab[2][13];
  214. int i,j,k;
  215. int leap;
  216. int year;
  217. int yearday;
  218. int month;
  219. int day;
  220.  
  221. bdos (155,temp);
  222. if(temp[0] == 761)
  223. {
  224.     printf("No TOD entered \n");
  225.     exit(0);
  226. }
  227. for (yearday = temp[0],year = 2;;)
  228. {
  229. if ((yearday - 365) < 0)
  230.     break;
  231. yearday -= 365;
  232. year++;
  233. if ((yearday - 365) < 0)
  234.     break;
  235. yearday -=365;
  236. year++;
  237. if ((yearday - 366) < 0)
  238.     break;
  239. yearday -=366;
  240. year++;
  241. if ((yearday - 365) < 0)
  242.     break;
  243. yearday -=365;
  244. year++;
  245. }
  246. initw(day_tab,"0,31,28,31,30,31,30,31,31,30,31,30,31");
  247. initw(&day_tab[1][0],"0,31,29,31,30,31,30,31,31,30,31,30,31");
  248. leap = year%4 == 0;
  249. for (i = 1;yearday > day_tab[leap][i];i++)
  250.     yearday -= day_tab[leap][i];
  251. itoa2(i,&date[0]);
  252. itoa2(yearday,&date[2]);
  253. year += 76;
  254. itoa2(year,&date[4]);
  255. return;
  256. }
  257. /*itoa2 is a little function used by getdate to convert an integer which must
  258. be between 0 and 99 to 2 ASCII characters*/
  259.  
  260. itoa2(n,s)
  261. char s[2];
  262. int n;
  263. {
  264. s[0] = n/10 + '0';
  265. s[1] = n%10 + '0';
  266. }
  267.  
  268. /*getfare is a specialized function used for computing base airline fares
  269. from gross fares. It receives dollars and cents as 2 integers and divides 
  270. them by the fraction represented by DIVA and DIVB (currently 1.05). The
  271. answer is output as ASCII characters in the array out1 with 4 digits of
  272. dollars,a decimal point and 2 digits of cents. Leading zeroes are turned 
  273. into blanks.*/
  274.  
  275. #define DIVA 1050
  276. #define DIVB 105
  277. getfare(dollars,cents,out1)
  278. int dollars;
  279. int cents;
  280. char out1[];
  281. {
  282.     int i;
  283.     int out[7];
  284.     for(i=0;i<7;i++)
  285.     {
  286.         out[i] = dollars/DIVA;
  287.         dollars = dollars%DIVA;
  288.         dollars = dollars*10;
  289.     }
  290.     for (i=4;i<7;i++)
  291.     {
  292.         cents = cents*10;
  293.         out[i] = out[i] + (cents/DIVB);
  294.         cents = cents%DIVB;
  295.     }
  296.     out[6] += 5;
  297.     for(i=6;i>=0;i--)
  298.         if(out[i] > 9)
  299.         {
  300.             out[i] -= 10;
  301.             out[i-1]++;
  302.         }
  303.  
  304.     for(i=0;out[i] == 0;i++)
  305.         out[i] +=47;
  306.     for(i=0;i<6;i++)
  307.         out1[i] = out[i] + 48;
  308.     out1[6] = out1[5];
  309.     out1[5] = out1[4];
  310.     out1[4] = '.';
  311. }
  312.  
  313. /*getsec will get a sector or group of sectors from the file represented 
  314. by fdd. The file must previously have been opened and it must have been
  315. initialized such that the number of sectors in the file are represented 
  316. by a single bit in the first 4 sectors of the file. Since the bit map 
  317. for allocation is already allocated itself the first 4 bits must be set 
  318. to 1 for this scheme to work. The function assumes that the file is 3568 
  319. sectors long (the size of the largest file in my computer system at 
  320. double density) so this constant should be adjusted when used on other
  321. systems. The input parameters permit the allocation of either 1,2,or
  322. 4 sector sizes. This is controlled via opt where 1 = 1,2 = 2, and anything 
  323. else = 4. It is possible to allocate several groups of sectors and this
  324. is controlled by nbr. Thus to allocate 15 2-sector groupings set nbr to
  325. 15 and opt to 2. All sectors are allocated on even boundaries. i.e the 
  326. first sector of a 4-sector allocation is always evenly divisible by itself
  327. (After all 0 is the first sector) Because it is necessary to read the bit
  328. map to allocate it is necessary to provide a 512-byte buffer for the getsec
  329. function to use to input it from disk. Finally, the array addr will contain 
  330. a list of the sectors which have been allocated. If a multi-sector allocation
  331. is requested then the first of the 2 or 4 sectors is provided. Notice you
  332. cannot mix sector sizes in a single call to getsec. If you want to check the
  333. out-of-sectors condition I suggest you set zeros in addr and check for an 
  334. answer of zero.*/
  335.  
  336. #define FILESIZE 446            /*3568/8*/
  337. getsec(nbr,addr,fdd,opt,buf)
  338. int nbr;
  339. int addr[];
  340. int fdd;
  341. int opt;
  342. char buf[];
  343. {
  344.     int i,j,k;
  345.     char mask;
  346.     int count;
  347.     rwblk(fdd,buf,0,4,0);
  348.     k = 0;
  349.     for(i=0;i<FILESIZE;i++)
  350.     {
  351.         if(buf[i] == 0377)
  352.             continue;
  353.         if(opt <= 1)
  354.         {
  355.             mask = 0200;
  356.             count = 1;
  357.         }
  358.         else if(opt == 2)
  359.         {
  360.             mask = 0300;
  361.             count = 2;
  362.         }
  363.         else
  364.         {
  365.             mask = 0360;
  366.             count = 4;
  367.         }
  368.         for(j=0;j<8;j+=count)
  369.         {
  370.             if(((buf[i]<<(j))&mask) == 0)
  371.             {
  372.                 addr[k++]=(i<<3) + (j);
  373.                 buf[i] = buf[i] | (mask >> j);
  374.                 if(k == nbr)
  375.                 {
  376.                     rwblk(fdd,buf,1,4,0);
  377.                     return(0);
  378.                 }
  379.             }
  380.         }
  381.     }
  382. }
  383.  
  384. /*itoa is right out of the bible. I don't know why Leor never included it*/
  385.  
  386. itoa(n,s)        /*convert n to chacracters in s */
  387. char s[];
  388. int n;
  389. {
  390.     int i, sign;
  391.  
  392.     if ((sign = n) < 0)   /* record sign */
  393.         n = -n;       /* make n positive */
  394.     i = 0;
  395.     do        /* generate digits in reverse order */
  396.     {
  397.         s[i++] = n%10+'0';  /* get next digit */
  398.     }
  399.     while ((n /= 10) > 0);  /*delete it */
  400.     if (sign < 0)
  401.         s[i++] = '-';
  402.     s[i] = '\0';
  403.     reverse(s);
  404. }
  405.  
  406. /*lineemp will take a set of ASCII characters from a terminal buffer of
  407. a size indicated by the integer size and called crtbuf, and compress them
  408. into an ASCII buffer called resbuf which has CR LF and terminates with a 
  409. control Z. The terminal buffer is checked for blank lines from the back 
  410. end and they are completely eliminated. lineemp returns the index to the
  411. control Z which provides the size of the disk buffer.*/
  412.  
  413. lineemp(resbuf,crtbuf,size)
  414. char resbuf[];
  415. char crtbuf[];
  416. int size;
  417. {
  418.     int i,j,k,m;
  419.     int lastline;
  420.  
  421.     for (i = size-1;i>0;i--)
  422.         if(crtbuf[i] != ' ')
  423.             break;
  424.     lastline = i/80;
  425.     for(i = k = m = 0;i<=lastline;i++,k+=80)
  426.     {
  427.         for(j = 80;j>0;j--)
  428.             if(crtbuf[k+j-1] != ' ')
  429.             break;
  430.         movmem(&crtbuf[k],&resbuf[m],j);
  431.         m = m + j;
  432.         resbuf[m++] = 13;
  433.         resbuf[m++] = 10;
  434.     }
  435.     resbuf[m] = 26;
  436.     return(m);
  437. }
  438.  
  439. /*linefull is the opposite of lineemp. It takes a typical text file from 
  440. disk and puts it into a terminal buffer,throwing out the CR and LF and 
  441. setting all unused characters to blanks. Caution! linefull cannot use
  442. tabs.*/
  443.  
  444. linefull(resbuf,crtbuf)
  445. char *resbuf;
  446. char *crtbuf;
  447. {
  448.     char *line;
  449.     char c;
  450.  
  451.     line = crtbuf;
  452.     while((c = *resbuf++) != 26)
  453.     {
  454.         if(c == 13)
  455.         {
  456.             resbuf++;
  457.             crtbuf = line = line + 80;
  458.             continue;
  459.         }
  460.         *crtbuf++ = c;
  461.     }
  462. }
  463.  
  464. /*list will output a buffer of characters to the list device using the CPM
  465. BDOS 5 function. The number of characters is specified by nbr. This function
  466. is necessary because some idiot at Digital Research required a $ to terminate
  467. the printer output and therefore you can't print any buffers with a $ in 
  468. them*/
  469.  
  470. list(stadd,nbr)
  471. char stadd[];
  472. int nbr;
  473. {
  474.     int i;
  475.     for ( i = 0; i < nbr; i++)
  476.     {
  477.         if (stadd[i] == '_')
  478.             stadd[i] = ' ';
  479.         bdos (5,stadd[i]);
  480.     }
  481. }
  482.  
  483. /*nextline searches an ASCII buffer for the beginning of the next line. If
  484. it finds at least one more line it exits with an integer pointing to the
  485. first character of that line. Else it exits with a -1.  j specifies the 
  486. offset into the buffer to start the search. */
  487.  
  488. nextline(resbuf,j)
  489. char resbuf[];
  490. int j;
  491. {
  492.     while (resbuf[j] != 13) 
  493.     {
  494.         if (resbuf[j] == 26)
  495.             return (-1);
  496.         j++;
  497.     }
  498.     j++;
  499.     if (resbuf[++j] == 26)
  500.         return (-1);
  501.     return(j);
  502. }
  503.  
  504. /*percent will take the dollars in array money[0] and the cents in array
  505. money[1], multiply it by the percent value in array money[2], and leave
  506. the answer as unsigned integers with dollars in array money[3], and cents
  507. in array money[4]. Proper rounding is used and cents are guaranteed to be
  508. less then 100. Caution! Do not use with negative numbers. */
  509.  
  510. percent(money)
  511. unsigned money[];
  512. {
  513.     unsigned i,j;
  514.     i = money[0] * money[2];
  515.     j = money[1] * money[2];
  516.     j = j + 50;
  517.     j = j/100;
  518.     money[3] = i/100;
  519.     money[4] = (i%100) + j;
  520.     if (money[4] > 99)
  521.     {
  522.         money[4] -= 100;
  523.         money[3] ++;
  524.     }
  525.     return;
  526. }
  527.  
  528. /*putcity will move 3 characters from array s1 and put them in array s2. It
  529. will then add a zero to array s2*/
  530.  
  531. putcity(s1,s2)
  532. char *s1;
  533. char *s2;
  534. {
  535.     int i;
  536.     for (i=0;i<3;i++)
  537.         *s2++ = *s1++;
  538.     *s2 = 0;
  539. }
  540.  
  541. /*putsec is the opposite of getsec. It will release sectors back to the system.
  542. It has similar options to getsec and like getsec it cannot mix options. If 
  543. putsec gets a sector number to release which is out of range or if the sector
  544. to be released is not currently set it will exit with a -1 and display an 
  545. alarm on the terminal*/
  546.  
  547. putsec(nbr,addr,fdd,opt,buf)
  548. int nbr;
  549. int addr[];
  550. int fdd;
  551. int opt;
  552. char buf[];
  553. {
  554.     int i,j,k;
  555.     char mask;
  556.     rwblk(fdd,buf,0,4,0);
  557.     if(opt <= 1)
  558.         mask = 0200;
  559.     else if(opt == 2)
  560.         mask = 0300;
  561.     else
  562.         mask = 0360;
  563.     for(i=0;i < nbr;i++)
  564.     {
  565.         if(addr[i] < FILESIZE * 8)
  566.         {
  567.             j = addr[i] >> 3;
  568.             k = addr[i] & 7;
  569.             if(((buf[j] << k) & mask) == mask)
  570.             {
  571.                 buf[j] =buf[j] & ~(mask >> k);
  572.                 continue;
  573.             }
  574.         }
  575.         printf("release err\n");
  576.         i = -1;
  577.         break;
  578.     }
  579.     rwblk(fdd,buf,1,4,0);
  580.     return(i);
  581. }
  582.  
  583. /*reverse is another routine from the bible*/
  584.  
  585. reverse(s)             /*reverse string s in place */
  586. char s[];
  587. {
  588.     int c,i,j;
  589.     
  590.     for(i=0,j=strlen(s)-1;i<j;i++,j--)
  591.     {
  592.         c = s[i];
  593.         s[i] = s[j];
  594.         s[j] = c;
  595.     }
  596. }
  597.  
  598. /*rwblk combines read,write,and seek into one function. If you tend to use
  599. seek + read or seek + write a lot it will save you space. The parameters 
  600. are fdd - the file descriptor, buf - the data buffer to read or write from,
  601. rw - read/write flag 0 = read, nbc - number of sectors, sbc - starting 
  602. sector.*/
  603.  
  604. rwblk(fdd,buf,rw,nbc,sbc)
  605. int fdd;
  606. char buf[];
  607. int rw;
  608. int nbc;
  609. int sbc;
  610. {
  611.     int i;
  612.     if((i == seek(fdd,sbc,0)) != -1)
  613.         if(rw == 0)
  614.             while((i = read(fdd,buf,nbc)) != -1)
  615.                 return(i);
  616.         else 
  617.             while((i = write(fdd,buf,nbc)) != -1)
  618.                 return(i);
  619.     printf("disk error");
  620.     return(i);
  621. }
  622. /*stgcmp is similar to strcmp. It does not require a zero to end the 
  623. string. Instead it has a character count as the parameter nbr. stgcmp
  624. will compare upper and lower case characters as equals and does not do
  625. an arithmetic comparison. The exit parameter is either 1 (TRUE) for 
  626. compare or zero (FALSE) for no compare.*/
  627.  
  628. stgcmp(rr,ss,nbr)
  629. char rr[];
  630. char ss[];
  631. int nbr;
  632. {
  633.     int i;
  634.     
  635.     for(i = 0;i < nbr; i++)
  636.         if(toupper(rr[i]) != toupper(ss[i]))
  637.             return(0);
  638.     return(1);
  639. }
  640.  
  641. /*submoney is identical to admoney except it subtracts rather than adds. 
  642. Since the money in array money[0] and money[1] is subtracted from the 
  643. money in array money[2] and array money[3] it is very important to make 
  644. sure that array money[2] and money[3] are larger than array money[0] and
  645. money[1]. Array money[4] contains the dollar answer and array money[5]
  646. contains the cents answer. */
  647.  
  648. submoney(money)
  649. unsigned money[];
  650. {
  651.     money[4] = money[2] - money[0];
  652.     if (money[3] < money[1])
  653.     {
  654.         money[3] +=100;
  655.         money[4]--;
  656.     }
  657.     money[5] = money[3] - money[1];
  658.     return(0);
  659. }
  660.